package com.jch.ft.test;

import com.alibaba.fastjson.JSON;
import com.jch.ft.codec.ObjectDecoder;
import com.jch.ft.codec.ObjectEncoder;
import com.jch.ft.domain.Constants;
import com.jch.ft.domain.FileBurstData;
import com.jch.ft.domain.FileBurstInstruct;
import com.jch.ft.domain.FileTransferProtocol;
import com.jch.ft.util.FileUtil;
import com.jch.ft.util.MsgUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

public class NettyClient {

    public static void main(String[] args) {
        EventLoopGroup worker = new NioEventLoopGroup();

        Bootstrap b = new Bootstrap()
                .group(worker)
                .channel(NioSocketChannel.class)
                .option(ChannelOption.AUTO_READ,true)
                .handler(new ChannelInitializer<SocketChannel>() {

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ObjectDecoder(FileTransferProtocol.class));
                        ch.pipeline().addLast(new ObjectEncoder(FileTransferProtocol.class));

                        ch.pipeline().addLast(new ChannelInboundHandlerAdapter(){

                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
                                // 断言 msg 为 FileTransferProtocol 类对象
                                assert msg instanceof FileTransferProtocol;
                                FileTransferProtocol fileTransferProtocol = (FileTransferProtocol) msg;
                                switch (fileTransferProtocol.getTransferType()){
                                    case 1: // 文件传输指令
                                        FileBurstInstruct fileBurstInstruct = (FileBurstInstruct) fileTransferProtocol.getTransferObject();
                                        // 传输完成
                                        if (Constants.FileStatus.COMPLETE == fileBurstInstruct.getStatus()) {
                                            ctx.flush(); // 刷新通道
                                            ctx.close(); // 关闭通道
                                            System.exit(-1); // 退出
                                            return;
                                        }
                                        FileBurstData fileBurstData = FileUtil.readFile(fileBurstInstruct.getClientFileUrl(),fileBurstInstruct.getReadIndex());
                                        ctx.writeAndFlush(MsgUtil.buildTransferData(fileBurstData));

                                        System.out.println(dateFormat.format(new Date()) + " 收到服务器的传输指令：" + JSON.toJSONString(fileBurstInstruct));
                                        break;
                                    default:
                                        break;
                                }

                                // 模拟传输过程中断
//                                System.out.println(dateFormat.format(new Date()) + "断点");
//                                ctx.flush();
//                                ctx.close();
//                                System.exit(-1);
                            }

                        });
                    }
                });

        try {
            ChannelFuture cf = b.connect("127.0.0.1",1128).sync();
            System.out.println("客户端启动！");

            File file = new File("E:\\jch\\字节码编程.pdf");
//            File file = new File("E:\\jch\\bg\\test.jpg");
            System.out.println("文件名：" + file.getName());
            System.out.println("文件绝对路径：" + file.getAbsolutePath());
            System.out.println("文件大小：" + file.length());
            // 组装文件传输请求
            FileTransferProtocol fileTransferProtocol = MsgUtil.buildRequestTransferFile(file.getAbsolutePath(),file.getName(),file.length());
            // 发送请求
            cf.channel().writeAndFlush(fileTransferProtocol);

            cf.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            worker.shutdownGracefully();
        }
    }
}
